<template>
  <el-main>
    <el-card class="device-detail-card">
      <!-- 更新页面标题样式 -->
      <div class="page-header">
        <div class="page-title">设备详情</div>
        <div class="page-subtitle">设备信息查看与管理</div>
      </div>
      
      <div class="device-info-flex">
        <div class="left-info-col" style="min-width: 100px;">
          <div class="img-qrcode-row">
            <div class="img-box">
              <img :src="getDeviceImage(device)" class="device-img" alt="设备图片" :style="'cursor:' + (device.image ? 'pointer' : 'default')" @click="device.image && (showImageDialog = true)" @error="e => e.target.src = placeholderImg" />
            </div>
            <div class="qrcode-box">
              <qrcode-vue :value="getDeviceUrl(device)" :size="90" :id="`qrcode-svg-${device.objectId}`" render-as="canvas" />
            </div>
          </div>
          <div class="card-actions qr-actions">
            <el-button size="small" @click="downloadQRCodeCard(device)">下载二维码</el-button>
            <el-button size="small" @click="printQRCodeCard(device)">打印二维码</el-button>
          </div>
        </div>
        <div class="device-info-block beautify-info-block">
          <div class="device-title-row">
            <span class="device-name">{{ device.name || '无' }}</span>
            <el-tag
              v-if="tagType"
              :type="tagType"
              effect="plain"
              style="margin-left:12px;"
            >
              {{ device.status || '未知' }}
            </el-tag>
            <el-tag
              v-else
              effect="plain"
              style="margin-left:12px;"
            >
              {{ device.status || '未知' }}
            </el-tag>
          </div>
          <div class="device-status-switch" style="margin-bottom: 10px;">
            <span style="margin-right: 8px; font-weight: bold;">状态切换</span>
            <el-button-group>
              <el-button :type="device.value && device.value.status === '正常运行' ? 'success' : 'default'" @click="onSetDeviceStatus('正常运行')">正常运行</el-button>
              <el-button :type="device.value && device.value.status === '带病运行' ? 'warning' : 'default'" @click="onSetDeviceStatus('带病运行')">带病运行</el-button>
              <el-button :type="device.value && device.value.status === '故障维修' ? 'danger' : 'default'" @click="onSetDeviceStatus('故障维修')">故障维修</el-button>
              <el-button :type="device.value && device.value.status === '备用' ? 'info' : 'default'" @click="onSetDeviceStatus('备用')">备用</el-button>
              <el-button :type="device.value && device.value.status === '报废' ? 'primary' : 'default'" @click="onSetDeviceStatus('报废')">报废</el-button>
            </el-button-group>
          </div>
          <el-divider content-position="left">基础信息</el-divider>
          <div class="device-meta-row">
            <div class="device-meta"><b>规格型号：</b>{{ device.model || '无' }}</div>
            <div class="device-meta"><b>设备编号：</b><span class="meta-highlight">{{ device.code || '无' }}</span></div>
          </div>
          <div class="device-meta-row">
            <div class="device-meta"><b>安装地点：</b>{{ device.location || '无' }}</div>
            <div class="device-meta"><b>负责人：</b>{{ device.manager || '无' }}</div>
          </div>
          <el-divider content-position="left">采购与维护</el-divider>
          <div class="device-meta-row">
            <div class="device-meta"><b>到货日期：</b>{{ device.arrivalDate ? new Date(device.arrivalDate).toLocaleDateString() : '无' }}</div>
            <div class="device-meta"><b>生产厂家：</b>{{ device.manufacturer || '无' }}</div>
          </div>
          <div class="device-meta-row">
            <div class="device-meta"><b>校正方案：</b>{{ device.calibrationPlan || '无需校正' }}</div>
            <div class="device-meta"><b>最近检查时间：</b>{{ latestCheckTime }}</div>
          </div>
        </div>
      </div>
      <div class="action-btn-row">
        <el-button v-if="!isGuestMode" class="action-btn" type="primary" @click="goEditDevice">编辑</el-button>
        <el-button class="action-btn" type="success" @click="onCalibration">校正</el-button>
        <el-button class="action-btn" type="danger" @click="onRepair">报修</el-button>
      </div>
    </el-card>
    <el-card style="margin-top: 18px;">
      <div style="font-weight: bold; margin-bottom: 8px;">关联备件</div>
      <el-table :data="spareParts" size="small" border>
        <el-table-column prop="name" label="备件名称" width="200" show-overflow-tooltip />
        <el-table-column prop="specification" label="规格型号" width="200" show-overflow-tooltip />
        <el-table-column label="存放位置" width="200">
          <template #default="scope">
            {{ getSparePartLocation(scope.row) }}
          </template>
        </el-table-column>
        <el-table-column prop="qty" label="数量" width="100" />
        <el-table-column label="操作" width="200">
          <template #default="scope">
            <el-button v-if="!isGuestMode" size="small" @click="editSparePart(scope.$index)">编辑</el-button>
            <el-button v-if="!isGuestMode" size="small" type="danger" @click="deleteSparePart(scope.$index)">删除</el-button>
            <el-button v-if="!isGuestMode" size="small" type="success" @click="openUseSparePartDialog(scope.$index)">支领</el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-button v-if="!isGuestMode" type="primary" size="small" style="margin:10px 0;" @click="openAddSparePartDialog">添加备件</el-button>
      <el-dialog v-if="!isGuestMode" v-model="showSparePartDialog" :title="editingSparePartIndex === null ? '添加备件' : '编辑备件'" width="400px">
        <el-form :model="sparePartForm" label-width="80px">
          <el-form-item label="备件名称">
            <el-select v-model="sparePartForm.name" filterable placeholder="请选择备件" @change="onSparePartChange">
              <el-option
                v-for="sp in availableSpareParts"
                :key="sp.objectId"
                :label="sp.name"
                :value="sp.name"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="规格型号">
            <el-input v-model="sparePartForm.specification" disabled />
          </el-form-item>
          <el-form-item label="数量"><el-input-number v-model="sparePartForm.qty" :min="1" /></el-form-item>
          <el-form-item label="存放位置">
            <el-select v-model="sparePartForm.location" filterable allow-create default-first-option placeholder="请选择或输入存放位置">
              <el-option v-for="loc in locations" :key="loc" :label="loc" :value="loc" />
            </el-select>
          </el-form-item>
        </el-form>
        <template #footer>
          <el-button @click="showSparePartDialog = false">取消</el-button>
          <el-button type="primary" @click="saveSparePart">保存</el-button>
        </template>
      </el-dialog>
    </el-card>
    <el-card style="margin-top:24px;">
      <el-tabs v-model="activeTab">
        <el-tab-pane label="操作记录" name="records">
          <el-table :data="records" border>
            <el-table-column prop="type" label="类型" width="100" />
            <el-table-column prop="content" label="内容" width="200" />
            <el-table-column prop="operator" label="操作人" width="100" />
            <el-table-column prop="date" label="时间" width="140">
              <template #default="scope">
                {{ scope.row.date ? new Date(scope.row.date).toLocaleString() : '' }}
              </template>
            </el-table-column>
            <el-table-column prop="result" label="结果" width="100" />
            <el-table-column prop="status" label="状态" width="100" />
          </el-table>
        </el-tab-pane>
      </el-tabs>
    </el-card>
    <el-dialog v-model="showImageDialog" width="400px" :show-close="true" title="图片预览" center>
      <img :src="getDeviceImage(device)" alt="设备大图" style="max-width:100%;max-height:60vh;display:block;margin:0 auto;" />
    </el-dialog>
    <!-- 校正弹窗 -->
    <el-dialog v-model="showCalibrationDialog" title="校正" width="400px">
      <el-form :model="calibrationForm" label-width="80px">
        <el-form-item label="结果">
          <el-select v-model="calibrationForm.result" placeholder="请选择">
            <el-option label="合格" value="合格" />
            <el-option label="不合格" value="不合格" />
          </el-select>
        </el-form-item>
        <el-form-item label="备注" prop="remark" :required="false">
          <el-input v-model="calibrationForm.remark" placeholder="校正备注（可选）" />
        </el-form-item>
        <el-form-item label="操作人">
          <el-input v-model="calibrationForm.operator" placeholder="填写操作人" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="showCalibrationDialog = false">取消</el-button>
        <el-button type="primary" @click="submitCalibration">提交</el-button>
      </template>
    </el-dialog>
    <!-- 报修弹窗 -->
    <el-dialog v-model="showRepairDialog" title="报修" width="400px">
      <el-form :model="repairForm" label-width="80px">
        <el-form-item label="故障描述">
          <el-input v-model="repairForm.desc" placeholder="请填写故障描述" />
        </el-form-item>
        <el-form-item label="报修人">
          <el-input v-model="repairForm.reporter" placeholder="请填写报修人" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="showRepairDialog = false">取消</el-button>
        <el-button type="primary" @click="submitRepair">提交</el-button>
      </template>
    </el-dialog>
    <el-dialog v-model="showUseSparePartDialog" title="支领备件" width="400px">
      <el-form :model="useSparePartForm" label-width="80px">
        <el-form-item label="备件名称"><el-input v-model="useSparePartForm.name" disabled /></el-form-item>
        <el-form-item label="规格型号"><el-input v-model="useSparePartForm.specification" disabled /></el-form-item>
        <el-form-item label="支领数量">
          <el-input-number v-model="useSparePartForm.qty" :min="1" :max="useSparePartForm.maxQty" />
        </el-form-item>
        <el-form-item label="支领人"><el-input v-model="useSparePartForm.user" /></el-form-item>
        <el-form-item label="备注"><el-input v-model="useSparePartForm.remark" /></el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="showUseSparePartDialog = false">取消</el-button>
        <el-button type="primary" @click="submitUseSparePart">确定支领</el-button>
      </template>
    </el-dialog>
    <el-dialog v-if="!isGuestMode" v-model="showEditDeviceDialog" title="编辑设备信息" width="500px">
      <el-form :model="editDeviceForm" label-width="100px">
        <el-form-item label="设备名称"><el-input v-model="editDeviceForm.name" required /></el-form-item>
        <el-form-item label="设备图片">
          <el-upload :show-file-list="false" :before-upload="beforeEditImageUpload" accept="image/*">
            <el-button>上传图片</el-button>
          </el-upload>
          <img v-if="editDeviceForm.imageUrl" :src="editDeviceForm.imageUrl" alt="设备图片" class="device-thumb" />
        </el-form-item>
        <el-form-item label="规格型号"><el-input v-model="editDeviceForm.model" /></el-form-item>
        <el-form-item label="设备编码"><el-input v-model="editDeviceForm.code" /></el-form-item>
        <el-form-item label="安装地点">
          <el-select v-model="editDeviceForm.location" filterable allow-create default-first-option placeholder="请选择或输入安装地点">
            <el-option v-for="loc in locations" :key="loc" :label="loc" :value="loc" />
          </el-select>
        </el-form-item>
        <el-form-item label="负责人"><el-input v-model="editDeviceForm.manager" /></el-form-item>
        <el-form-item label="到货日期">
          <el-date-picker v-model="editDeviceForm.arrivalDate" type="date" />
        </el-form-item>
        <el-form-item label="生产厂家"><el-input v-model="editDeviceForm.manufacturer" /></el-form-item>
        <el-form-item label="校正方案">
          <el-select v-model="editDeviceForm.calibrationPlan" placeholder="请选择">
            <el-option label="每班校正" value="每班校正" />
            <el-option label="无需校正" value="无需校正" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="showEditDeviceDialog = false">取消</el-button>
        <el-button type="primary" @click="saveEditDevice">保存</el-button>
      </template>
    </el-dialog>
  </el-main>
</template>

<script setup>
import { ref, onMounted, watch, computed, inject, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import QrcodeVue from 'qrcode.vue'
import AV from '../leancloud'
import locations from '../assets/locations'
import imageCompression from 'browser-image-compression'

const placeholderImg = 'https://img.js.design/assets/img/64b7e2b6b6b3f7b2b7e2b6b6.png'
const device = ref({})
const records = ref([])
const spareParts = ref([])
const allSpareParts = ref([])
const activeTab = ref('records')
const showImageDialog = ref(false)
const isGuestMode = ref(localStorage.getItem('isGuestMode') === 'true')
const currentUsername = localStorage.getItem('currentUsername') || ''
const userRole = ref(localStorage.getItem('userRole') || 'user')

// 弹窗控制
const showCheckDialog = ref(false)
const showCalibrationDialog = ref(false)
const showRepairDialog = ref(false)
const showSparePartDialog = ref(false)
const editingSparePartIndex = ref(null)
const sparePartForm = ref({ name: '', specification: '', qty: 1 })

// 表单数据
const checkForm = ref({ status: '', remark: '', operator: '' })
const calibrationForm = ref({ result: '合格', remark: '', operator: currentUsername })
const repairForm = ref({ desc: '', reporter: currentUsername })

const route = useRoute()
const router = useRouter()
const deviceId = ref('')
watch(() => route.query.id, (id) => {
  deviceId.value = id
  fetchDeviceDetail()
})
onMounted(() => {
  deviceId.value = route.query.id
  fetchDeviceDetail()
  fetchAllSpareParts()
})
async function fetchAllSpareParts() {
  try {
    const query = new AV.Query('SparePart')
    query.limit(1000)
    const results = await query.find()
    allSpareParts.value = results.map(item => item.toJSON())
  } catch (e) {
    allSpareParts.value = []
  }
}
function getDeviceUrl(device) {
  const ip = '192.168.10.47'
  const port = '5173'
  const token = localStorage.getItem('sessionToken')
  return `http://${ip}:${port}/#/device-detail?id=${device.objectId}${token ? `&token=${token}` : ''}`
}
function drawBeautifulCard(ctx, device, qrCanvas, width, height) {
  // 复制 QRCodeManage.vue 的 drawBeautifulCard 代码 ...
  ctx.save();
  ctx.shadowColor = 'rgba(58,122,254,0.18)';
  ctx.shadowBlur = 8;
  ctx.beginPath();
  ctx.rect(0, 0, width, height);
  ctx.closePath();
  const grad = ctx.createLinearGradient(0, 0, width, height);
  grad.addColorStop(0, '#f5faff'); grad.addColorStop(1, '#e3eefd');
  ctx.fillStyle = grad;
  ctx.fill();
  ctx.restore();
  const infoBarY = 0, infoBarH = 28;
  ctx.save();
  ctx.fillStyle = '#3a7afe';
  ctx.fillRect(0, infoBarY, width, infoBarH);
  ctx.restore();
  const qrX = 18, qrY = infoBarY + infoBarH + 14, qrW = 60, qrH = 60, qrR = 6, qrPad = 4;
  ctx.font = 'bold 14px Arial';
  ctx.fillStyle = '#fff';
  ctx.textAlign = 'left';
  const infoTitle = '设备信息';
  const infoTitleWidth = ctx.measureText(infoTitle).width;
  const infoTitleX = qrX + qrW/2 - infoTitleWidth/2;
  ctx.fillText(infoTitle, infoTitleX, infoBarY + infoBarH/2 + 5);
  ctx.strokeStyle = '#e3eefd';
  ctx.lineWidth = 1;
  ctx.beginPath();
  ctx.moveTo(16, infoBarY+infoBarH); ctx.lineTo(width-16, infoBarY+infoBarH);
  ctx.stroke();
  ctx.save();
  ctx.beginPath();
  ctx.moveTo(qrX+qrR, qrY);
  ctx.lineTo(qrX+qrW-qrR, qrY);
  ctx.quadraticCurveTo(qrX+qrW, qrY, qrX+qrW, qrY+qrR);
  ctx.lineTo(qrX+qrW, qrY+qrH-qrR);
  ctx.quadraticCurveTo(qrX+qrW, qrY+qrH, qrX+qrW-qrR, qrY+qrH);
  ctx.lineTo(qrX+qrR, qrY+qrH);
  ctx.quadraticCurveTo(qrX, qrY+qrH, qrX, qrY+qrH-qrR);
  ctx.lineTo(qrX, qrY+qrR);
  ctx.quadraticCurveTo(qrX, qrY, qrX+qrR, qrY);
  ctx.closePath();
  ctx.fillStyle = '#fff';
  ctx.fill();
  ctx.strokeStyle = '#d3d6db';
  ctx.lineWidth = 2;
  ctx.stroke();
  ctx.drawImage(qrCanvas, qrX+qrPad, qrY+qrPad, qrW-2*qrPad, qrH-2*qrPad);
  ctx.restore();
  ctx.font = '12px Arial';
  ctx.fillStyle = '#222';
  ctx.textAlign = 'left';
  const infoX = 90;
  const nameFontSize = 12, lineH = 18;
  ctx.font = nameFontSize + 'px Arial';
  const textBlockHeight = lineH;
  const infoY = qrY + qrH/2 - textBlockHeight/2 + 4;
  ctx.fillText('设备名称：' + (device.name||''), infoX, infoY - 1);
  ctx.fillText('规格型号：' + (device.model||''), infoX, infoY + lineH + 3);
  const underQrX = 18, underQrY = qrY+qrH+22, underLineH = 16, underWidth = width-36;
  ctx.font = '12px Arial';
  ctx.fillStyle = '#222';
  ctx.textAlign = 'left';
  function fillWrapText(text, x, y, maxWidth) {
    const words = text.split('');
    let line = '';
    let lineY = y;
    for(let i=0;i<words.length;i++){
      const testLine = line + words[i];
      const metrics = ctx.measureText(testLine);
      if(metrics.width > maxWidth && line) {
        ctx.fillText(line, x, lineY);
        line = words[i];
        lineY += underLineH;
      } else {
        line = testLine;
      }
    }
    if(line) ctx.fillText(line, x, lineY);
    return lineY;
  }
  ctx.font = '12px Arial';
  let y1 = fillWrapText('设备编号：' + (device.code||''), underQrX, underQrY-2, underWidth);
  fillWrapText('生产厂家：' + (device.manufacturer||''), underQrX, y1+underLineH+2, underWidth);
}
function downloadQRCodeCard(device) {
  const qrCanvas = document.querySelector(`#qrcode-svg-${device.objectId}`)
  if (!qrCanvas) {
    alert('未找到二维码Canvas元素');
    return
  }
  const width = 240, height = 160;
  const card = document.createElement('canvas');
  card.width = width;
  card.height = height;
  const ctx = card.getContext('2d');
  drawBeautifulCard(ctx, device, qrCanvas, width, height);
  const url = card.toDataURL('image/png');
  const a = document.createElement('a');
  a.href = url;
  a.download = `${device.name||'设备'}-二维码名片.png`;
  a.click();
}
function printQRCodeCard(device) {
  const qrCanvas = document.querySelector(`#qrcode-svg-${device.objectId}`)
  if (!qrCanvas) {
    alert('未找到二维码Canvas元素');
    return
  }
  const width = 240, height = 160;
  const card = document.createElement('canvas');
  card.width = width;
  card.height = height;
  const ctx = card.getContext('2d');
  drawBeautifulCard(ctx, device, qrCanvas, width, height);
  const url = card.toDataURL('image/png');
  const win = window.open('', '_blank');
  win.document.write('<html><head><title>打印二维码名片</title></head><body style="text-align:center;"><img src="' + url + '" style="margin:30px auto;display:block;"/><script>window.onload=function(){window.print();window.close();}<' + '/script></body></html>');
  win.document.close();
}
async function fetchDeviceDetail() {
  if (!deviceId.value) {
    ElMessage.error('未获取到设备ID，无法加载详情')
    return
  }
  try {
    const query = new AV.Query('Device')
    query.include('spareParts') // 包含关联的备件
    query.get(deviceId.value).then(async d => {
      device.value = {}
      await nextTick()
      device.value = { ...d.toJSON() }
      spareParts.value = Array.isArray(d.get('spareParts')) ? d.get('spareParts') : []
      records.value = [
        { type: '日常检查', content: '正常', operator: '张三', date: '2025-07-10', result: '通过', status: '正常' },
        { type: '校正', content: '校正完成', operator: '李四', date: '2025-07-05', result: '合格', status: '正常' },
        { type: '报修', content: '显示屏损坏', operator: '王五', date: '2025-07-01', result: '已修复', status: '已完成' }
      ]
    }).catch(e => {
      ElMessage.error('加载设备详情失败：' + e.message)
    })
  } catch (e) {
    ElMessage.error('加载设备详情失败：' + e.message)
  }
}

function handleBack() {
  ElMessage.info('返回综合办公页')
}
// 校正提交
async function submitCalibration() {
  if (!calibrationForm.value.result || !calibrationForm.value.operator) {
    ElMessage.warning('请填写完整信息');
    return;
  }
  // 打印参数
  console.log('校正参数:', calibrationForm.value, '设备ID:', device.value?.objectId);
  try {
    const CalibrationRecord = AV.Object.extend('DeviceActionRecord');
    const record = new CalibrationRecord();
    record.set('device', AV.Object.createWithoutData('Device', device.value?.objectId));
    record.set('type', '校正');
    record.set('content', '日常校正');
    record.set('operator', calibrationForm.value.operator);
    record.set('date', new Date());
    record.set('result', calibrationForm.value.result);
    record.set('status', '正常');
    await record.save();
    ElMessage.success('校正已提交');
    showCalibrationDialog.value = false;
    // 可选：刷新数据
  } catch (e) {
    ElMessage.error('校正保存失败: ' + (e.message || e.rawMessage));
    console.error('校正保存失败', e);
  }
}
// 报修提交
async function submitRepair() {
  if (!repairForm.value.desc || !repairForm.value.reporter) {
    ElMessage.warning('请填写完整信息');
    return;
  }
  // 打印参数
  console.log('报修参数:', repairForm.value, '设备ID:', device.value?.objectId);
  try {
    const RepairRecord = AV.Object.extend('RepairRecord');
    const record = new RepairRecord();
    record.set('device', AV.Object.createWithoutData('Device', device.value?.objectId));
    record.set('desc', repairForm.value.desc);
    record.set('reporter', repairForm.value.reporter);
    record.set('reportTime', new Date());
    record.set('status', '处理中');
    // 可选：生成报修单号
    function generateRepCode() {
      const now = new Date();
      const y = now.getFullYear();
      const m = String(now.getMonth() + 1).padStart(2, '0');
      const d = String(now.getDate()).padStart(2, '0');
      const h = String(now.getHours()).padStart(2, '0');
      const min = String(now.getMinutes()).padStart(2, '0');
      const s = String(now.getSeconds()).padStart(2, '0');
      return `BX${y}${m}${d}${h}${min}${s}${Math.floor(Math.random()*1000).toString().padStart(3,'0')}`;
    }
    record.set('repCode', generateRepCode());
    await record.save();
    ElMessage.success('报修已提交');
    showRepairDialog.value = false;
    // 可选：刷新数据
  } catch (e) {
    ElMessage.error('报修保存失败: ' + (e.message || e.rawMessage));
    console.error('报修保存失败', e);
  }
}
async function setDeviceStatus(status) {
  if (!device.value || !device.value.objectId) return
  try {
    const d = AV.Object.createWithoutData('Device', device.value.objectId)
    d.set('status', status)
    await d.save()
    device.value.status = status
    ElMessage.success('状态已更新')
    // 故障维修时自动写入报修记录并推送钉钉
    if (status === '故障维修') {
      // 写入报修记录（LeanCloud RepairRecord 表）
      try {
        const RepairRecord = AV.Object.extend('RepairRecord')
        const record = new RepairRecord()
        record.set('device', AV.Object.createWithoutData('Device', device.value.objectId))
        record.set('repCode', `AUTO${Date.now()}`)
        record.set('desc', '状态切换为故障维修')
        record.set('reporter', currentUsername)
        record.set('reportTime', new Date())
        record.set('status', '处理中')
        const acl = new AV.ACL()
        acl.setPublicReadAccess(true)
        acl.setPublicWriteAccess(true)
        record.setACL(acl)
        await record.save()
      } catch (e) {
        ElMessage.error('自动写入报修记录失败')
      }
      // 钉钉推送
      try {
        const msg = {
          content: `【设备报修通知】\n设备名称：${device.value.name}\n设备编号：${device.value.code}\n报修人：${currentUsername}\n描述：状态切换为故障维修\n时间：${new Date().toLocaleString()}`
        }
        const res = await fetch('https://hellowodingtalk-lsmprvoblr.cn-beijing.fcapp.run', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(msg)
        })
        const data = await res.json()
        if (data.errcode === 0) {
          ElMessage.success('钉钉自动报修推送成功')
        } else {
          ElMessage.error('钉钉推送失败：' + data.errmsg)
        }
      } catch (e) {
        ElMessage.error('钉钉推送异常：' + e.message)
      }
    }
    // 通知设备列表页刷新
    localStorage.setItem('deviceListShouldRefresh', '1')
    fetchDeviceDetail()
  } catch (e) {
    ElMessage.error('状态更新失败')
  }
}
async function onChangeCalibrationPlan(plan) {
  if (!device.value || !device.value.objectId) return
  try {
    const d = AV.Object.createWithoutData('Device', device.value.objectId)
    d.set('calibrationPlan', plan)
    await d.save()
    device.value.calibrationPlan = plan
    ElMessage.success('校正方案已切换为：' + plan)
  } catch (e) {
    ElMessage.error('切换失败：' + (e.message || e.rawMessage))
  }
}
function openAddSparePartDialog() {
  editingSparePartIndex.value = null
  sparePartForm.value = { name: '', specification: '', qty: 1, location: '' }
  showSparePartDialog.value = true
}
function editSparePart(idx) {
  editingSparePartIndex.value = idx
  const row = spareParts.value[idx]
  const sp = allSpareParts.value.find(sp => sp.name === row.name)
  sparePartForm.value = { ...row, location: sp && sp.location ? sp.location : '' }
  showSparePartDialog.value = true
}
async function saveSparePartsToBackend() {
  if (!device.value.objectId) return
  const d = AV.Object.createWithoutData('Device', device.value.objectId)
  d.set('spareParts', spareParts.value)
  await d.save()
  ElMessage.success('关联备件已保存')
}
async function saveSparePart() {
  if (!sparePartForm.value.name) {
    ElMessage.warning('请选择备件')
    return
  }
  const data = { ...sparePartForm.value }
  if ('id' in data) delete data.id
  if (editingSparePartIndex.value === null) {
    spareParts.value.push(data)
  } else {
    spareParts.value[editingSparePartIndex.value] = data
  }
  showSparePartDialog.value = false
  // 同步更新SparePart表location字段
  if (data.objectId && data.location) {
    try {
      const sparePart = AV.Object.createWithoutData('SparePart', data.objectId)
      sparePart.set('location', data.location)
      await sparePart.save()
      await fetchAllSpareParts()
    } catch (e) {
      ElMessage.error('同步存放位置到备件库失败：' + (e.message || e.rawMessage))
    }
  }
  saveSparePartsToBackend()
}
function deleteSparePart(idx) {
  ElMessageBox.confirm('确定要删除该备件吗？', '提示', { type: 'warning' })
    .then(() => {
      spareParts.value.splice(idx, 1)
      ElMessage.success('已删除')
      saveSparePartsToBackend()
    })
}
const tagType = computed(() => {
  if (device.value.status === '正常运行') return 'success'
  if (device.value.status === '带病运行') return 'warning'
  if (device.value.status === '故障维修') return 'danger'
  if (device.value.status === '备用') return 'info'
  return null
})
const availableSpareParts = computed(() => {
  // 编辑时允许当前备件重复
  const usedNames = spareParts.value.map((sp, idx) => idx === editingSparePartIndex.value ? null : sp.name).filter(Boolean)
  return allSpareParts.value.filter(sp => !usedNames.includes(sp.name))
})
function onSparePartChange(name) {
  const sp = allSpareParts.value.find(sp => sp.name === name)
  if (sp) {
    sparePartForm.value.specification = sp.specification
    sparePartForm.value.objectId = sp.objectId
    sparePartForm.value.location = sp.location || ''
    if ('id' in sparePartForm.value) delete sparePartForm.value.id
  } else {
    sparePartForm.value.specification = ''
    sparePartForm.value.objectId = ''
    sparePartForm.value.location = ''
  }
}
const showUseSparePartDialog = ref(false)
const useSparePartForm = ref({ name: '', specification: '', qty: 1, maxQty: 1, user: '', remark: '' })
let useSparePartIndex = null
function openUseSparePartDialog(idx) {
  useSparePartIndex = idx
  const sp = spareParts.value[idx]
  useSparePartForm.value = {
    name: sp.name,
    specification: sp.specification,
    qty: 1,
    maxQty: sp.qty,
    user: '',
    remark: ''
  }
  showUseSparePartDialog.value = true
}
async function submitUseSparePart() {
  const form = useSparePartForm.value
  if (!form.user) {
    ElMessage.warning('请填写支领人')
    return
  }
  if (form.qty < 1 || form.qty > form.maxQty) {
    ElMessage.warning('支领数量不合法')
    return
  }
  // 扣减数量
  spareParts.value[useSparePartIndex].qty -= form.qty
  if (spareParts.value[useSparePartIndex].qty < 0) spareParts.value[useSparePartIndex].qty = 0
  showUseSparePartDialog.value = false
  await saveSparePartsToBackend()
  // 记录操作
  records.value.unshift({
    type: '支领',
    content: `支领${form.qty}个${form.name}${form.remark ? '，备注：' + form.remark : ''}`,
    operator: form.user,
    date: new Date().toISOString(),
    result: '已支领',
    status: '完成'
  })
  ElMessage.success('支领成功')
}
function getSparePartLocation(row) {
  const sp = allSpareParts.value.find(sp => sp.objectId === row.objectId)
  return sp && sp.location ? sp.location : (row.location || '')
}
function getDeviceImage(device) {
  if (!device) return placeholderImg
  if (typeof device.image === 'string') return device.image || placeholderImg
  if (device.image && device.image.url) return typeof device.image.url === 'function' ? device.image.url() : device.image.url
  return placeholderImg
}
const showEditDeviceDialog = ref(false)
const editDeviceForm = ref({
  name: '',
  imageFile: null,
  imageUrl: '',
  model: '',
  code: '',
  location: '',
  manager: '',
  arrivalDate: '',
  manufacturer: '',
  calibrationPlan: '',
  status: ''
})
function goEditDevice() {
  // 填充当前设备信息
  Object.assign(editDeviceForm.value, {
    name: device.value.name || '',
    imageFile: null,
    imageUrl: device.value.image ? (typeof device.value.image === 'string' ? device.value.image : (device.value.image.url || '')) : '',
    model: device.value.model || '',
    code: device.value.code || '',
    location: device.value.location || '',
    manager: device.value.manager || '',
    arrivalDate: device.value.arrivalDate || '',
    manufacturer: device.value.manufacturer || '',
    calibrationPlan: device.value.calibrationPlan || '',
    status: device.value.status || ''
  })
  showEditDeviceDialog.value = true
}
async function beforeEditImageUpload(file) {
  const compressedFile = await imageCompression(file, { maxSizeMB: 0.2, maxWidthOrHeight: 800, useWebWorker: true })
  editDeviceForm.value.imageFile = compressedFile
  editDeviceForm.value.imageUrl = URL.createObjectURL(compressedFile)
  return false
}
async function saveEditDevice() {
  try {
    const d = AV.Object.createWithoutData('Device', device.value.objectId)
    Object.entries(editDeviceForm.value).forEach(([k, v]) => {
      if (k === 'imageFile' || k === 'imageUrl') return
      if (v) d.set(k, v)
      else d.unset(k)
    })
    if (editDeviceForm.value.imageFile) {
      const avFile = new AV.File(editDeviceForm.value.imageFile.name, editDeviceForm.value.imageFile)
      await avFile.save()
      d.set('image', avFile)
    }
    await d.save()
    ElMessage.success('保存成功')
    showEditDeviceDialog.value = false
    fetchDeviceDetail()
  } catch (e) {
    ElMessage.error('保存失败：' + (e.message || e.rawMessage))
  }
}
// 在<script setup>中新增计算属性：
const latestCheckTime = computed(() => {
  const times = []
  const rawTimes = []
  // 设备添加时间
  if (device.value.createdAt) {
    times.push(new Date(device.value.createdAt).getTime())
    rawTimes.push(device.value.createdAt)
  }
  // 到货日期
  if (device.value.arrivalDate) {
    times.push(new Date(device.value.arrivalDate).getTime())
    rawTimes.push(device.value.arrivalDate)
  }
  // 操作记录中的状态变更、校正、报修
  if (Array.isArray(records.value)) {
    records.value.forEach(r => {
      if ((r.type && (r.type.includes('状态') || r.type.includes('校正') || r.type.includes('报修'))) && r.date) {
        times.push(new Date(r.date).getTime())
        rawTimes.push(r.date)
      }
    })
  }
  if (!times.length) return '无'
  const maxTime = Math.max(...times)
  const idx = times.findIndex(t => t === maxTime)
  const raw = rawTimes[idx] || ''
  const d = new Date(maxTime)
  // 判断原始字符串是否包含时分秒
  if (typeof raw === 'string' && (raw.includes('T') || raw.includes(':'))) {
    return d.toLocaleString()
  } else {
    return d.toLocaleDateString()
  }
})
// 2. 登录拦截统一方法
const showLogin = inject('showLogin')
function requireLogin(action) {
  if (isGuestMode.value) {
    ElMessage.warning('请先登录后操作')
    localStorage.setItem('loginRedirect', router.currentRoute.value.fullPath)
    showLogin && showLogin()
    return
  }
  action()
}
// 3. 包装操作方法
function onSetDeviceStatus(status) {
  requireLogin(() => setDeviceStatus(status))
}
function onCalibration() {
  requireLogin(() => showCalibrationDialog.value = true)
}
function onRepair() {
  requireLogin(() => showRepairDialog.value = true)
}
function toggleCalibrationPlanDetail() {
  if (!device.value || !device.value.objectId) return
  const next = device.value.calibrationPlan === '每班校正' ? '无需校正' : '每班校正'
  const d = AV.Object.createWithoutData('Device', device.value.objectId)
  d.set('calibrationPlan', next)
  d.save().then(() => {
    device.value.calibrationPlan = next
    ElMessage.success('校正方案已切换为：' + next)
    fetchDeviceDetail()
  }).catch(e => {
    ElMessage.error('切换失败：' + (e.message || e.rawMessage))
  })
}
</script>

<style scoped>
.device-detail-card {
  margin-bottom: 24px;
  padding-bottom: 8px;
}
.page-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-bottom: 20px;
  padding-bottom: 10px;
  border-bottom: 1px solid #eee;
}
/* 页面标题样式已移至全局样式文件 */
.device-info-flex {
  display: flex;
  align-items: stretch;
  gap: 32px;
  margin-bottom: 12px;
  padding-top: 0;
}
.left-info-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
}
.img-box, .qrcode-box {
  width: 100px;
  height: 100px;
  border: 1px solid #888;
  border-radius: 6px;
  background: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0;
  box-sizing: border-box;
}
.device-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 6px;
  background: #fff;
  border: none;
  box-shadow: none;
  padding: 0;
}
.device-info-block {
  flex: 1;
  min-width: 220px;
  background: #f7faff;
  border-radius: 10px;
  padding: 18px 18px 10px 18px;
  box-shadow: 0 2px 8px 0 rgba(58,122,254,0.04);
  display: flex;
  flex-direction: column;
  gap: 0.5em;
}
.beautify-info-block {
  border: 1.5px solid #e0e6ed;
  background: linear-gradient(135deg, #f7faff 60%, #f5f6fa 100%);
}
.device-title-row {
  display: flex;
  align-items: center;
  font-size: 22px;
  font-weight: bold;
  margin-bottom: 10px;
  color: #2d3a4b;
}
.device-name {
  font-size: 22px;
  font-weight: bold;
}
.device-meta-row {
  display: flex;
  gap: 32px;
  margin-bottom: 2px;
  flex-wrap: wrap;
  justify-content: flex-start;
}
.device-meta {
  font-size: 15px;
  color: #222;
  min-width: 160px;
  margin-bottom: 2px;
  text-align: left;
}
.action-btn-row {
  display: flex;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.device-card {
  width: 320px;
  border: 2px solid #3a7afe;
  border-radius: 10px;
  background: linear-gradient(135deg, #f5faff 60%, #e3eefd 100%);
  padding: 18px 18px 12px 18px;
  box-shadow: 0 2px 8px 0 rgba(58,122,254,0.08);
  margin-bottom: 12px;
}
.card-title {
  font-size: 18px;
  font-weight: bold;
  color: #2d3a4b;
  margin-bottom: 10px;
}
.card-content {
  display: flex;
  align-items: flex-start;
  gap: 18px;
}
.qrcode-box {
  border: 1px solid #888;
  background: #fff;
  border-radius: 6px;
  width: 100px;
  height: 100px;
  min-width: 100px;
  min-height: 100px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  margin-top: 18px;
}
.info-box {
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 15px;
  color: #222;
}
.card-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
}
.card-actions .el-button {
  width: 100px;
  min-width: 100px;
  max-width: 100px;
  text-align: center;
  justify-content: center;
  align-items: center;
  display: flex;
  padding-left: 0 !important;
  padding-right: 0 !important;
}
.card-actions .el-button:last-child {
  margin-left: 1px;
}
.meta-highlight {
  color: #1677ff;
  font-weight: bold;
  letter-spacing: 1px;
}
.device-status-switch {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}
.device-thumb {
  width: 100px;
  height: 100px;
  object-fit: cover;
  border-radius: 6px;
  margin-top: 10px;
}
.img-qrcode-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 24px;
  margin-bottom: 18px;
}
.img-qrcode-row .img-box, .img-qrcode-row .qrcode-box {
  display: flex;
  flex-direction: column;
  align-items: center;
}
@media (max-width: 700px) {
  .page-header {
    text-align: left;
    padding-left: 10px;
    padding-bottom: 5px;
    align-items: flex-start;
  }
  .page-title {
    font-size: 20px;
  }
  .page-subtitle {
    font-size: 14px;
  }
  .device-info-flex {
    flex-direction: column;
    gap: 2px;
  }
  .img-qrcode-row {
    flex-direction: row;
    gap: 12px;
  }
  .img-qrcode-row .device-img {
    width: 80px;
    height: 80px;
  }
  .img-qrcode-row .qrcode-box qrcode-vue {
    width: 80px !important;
    height: 80px !important;
  }
  .qr-actions {
    display: none !important;
  }
  .img-qrcode-row .qrcode-box {
    margin-top: 1px;
  }
}
</style> 